package edu.caltech.android.info;

import java.util.ArrayList;
import java.util.Arrays;


import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import edu.caltech.android.R;
import edu.caltech.android.ShakeAlertActivity;
import edu.caltech.android.ShakeAlertService;
import edu.caltech.android.waveforms.WaveformDisplay;

/**
 * Display info about this application and client.
 * 
 * TODO make this a ListActivity
 * 
 * 
 * @author mfaulk
 * 
 */
public class ClientInfo extends Activity {
	private static final String TAG = "ClientInfo";
	private static final int SHAKE_MAP_ID = Menu.FIRST;
	private static final int WAVEFORM_ID = Menu.FIRST + 1;
	private static final int QUIT_ID = Menu.FIRST + 2;

	private ListView mainListView;
	private ArrayAdapter<String> listAdapter;

	// may be null
	private ShakeAlertService serviceBinder;

	private Handler handler = new Handler();
	private final long refreshDelayMillis = 1000;

	/**
	 * Periodically refresh the list of info. See
	 * http://android-developers.blogspot.com/2007/11/stitch-in-time.html
	 */
	private Runnable refreshListTask = new Runnable() {
		public void run() {
			//Log.v(TAG, "refreshing list...");
			populateList();

			handler.postDelayed(this, refreshDelayMillis);
		}
	};

	/**
	 * Handles the connection between the service and activity
	 */
	private ServiceConnection mConnection = new ServiceConnection() {
		public void onServiceConnected(ComponentName className, IBinder service) {
			// Called when the connection is made.
			serviceBinder = ((ShakeAlertService.ShakeAlertServiceBinder) service)
					.getService();
			populateList();
		}

		public void onServiceDisconnected(ComponentName className) {
			Log.d(TAG, "ShakeAlertService disconnected.");
			// Received when the service unexpectedly disconnects.
			serviceBinder = null;
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.v(TAG, "creating ClientInfo");
		setContentView(R.layout.client_info);

		mainListView = (ListView) findViewById(R.id.mainListView);

		// Create and populate a List of elements
		String[] elements = new String[] { "Getting Info..." };
		ArrayList<String> elementList = new ArrayList<String>();
		elementList.addAll(Arrays.asList(elements));

		// Create ArrayAdapter using the list.
		listAdapter = new ArrayAdapter<String>(this, R.layout.client_info_item,
				elementList);

		// Set the ArrayAdapter as the ListView's adapter.
		mainListView.setAdapter(listAdapter);

		// for implement clickable list items:
		// mainListView.setOnItemLongClickListener(listener);

		// bind to the ShakeAlertService to get application info and status
		Log.v(TAG, "binding to ShakeAlertService");
		Intent bindIntent = new Intent(ClientInfo.this, ShakeAlertService.class);
		bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);

		// periodic refreshes initialized in onResume
	}

	@Override
	protected void onResume() {
		super.onResume();
		// begin period refreshes
		handler.removeCallbacks(refreshListTask);
		handler.postDelayed(refreshListTask, refreshDelayMillis);
	}

	@Override
	protected void onPause() {
		super.onPause();
		handler.removeCallbacks(refreshListTask);
	}

	@Override
	protected void onDestroy() {
		Log.d(TAG, "unbinding from ShakeAlertService");
		unbindService(mConnection);
		super.onDestroy();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		boolean retVal = super.onCreateOptionsMenu(menu);

		menu.add(0, SHAKE_MAP_ID, 0, "Shake Map");
		menu.add(0, WAVEFORM_ID, 0, "Accelerometer");
		menu.add(0, QUIT_ID, 0, "Quit");
		return retVal;
	}

	private void populateList() {
		if (serviceBinder == null) {
			Log.v(TAG, "serviceBinder is null. Not populating.");
			return;
		}

		//Log.v(TAG, "populating.");
		String clientID = serviceBinder.getClientID();
		String clientName = serviceBinder.getClientName();
		String versionCode = "versionCode";
		String versionName = "versionName";
		String permissions = "permissions";
		String parameterVersion = serviceBinder.getParameterVersion();
		boolean networkPositionStatus = serviceBinder.networkPositionEnabled();
		boolean gpsStatus = serviceBinder.gpsEnabled();
		boolean wifiStatus = false;
		boolean mobileStatus = false;
		String sdStatus = "SD status"; // SD card
		String chargingStatus = serviceBinder.getBatteryStatus();

		try {
			// Read package name and version number from manifest
			PackageManager manager = this.getPackageManager();
			PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
			versionCode = Integer.toString(info.versionCode);
			versionName = info.versionName;
			// PermissionInfo[] permissionInfo = info.permissions;
			// permissions = "";
			// for (PermissionInfo p : permissionInfo) {
			// permissions += p.name + " ";
			// }
		} catch (Exception e) {
			e.printStackTrace();
		}

		// get wifi and mobile network status. Requires
		// android.permission.ACCESS_NETWORK_STATE and
		// android.permission.INTERNET
		try {
			final ConnectivityManager connMgr = (ConnectivityManager) this
					.getSystemService(Context.CONNECTIVITY_SERVICE);

			final android.net.NetworkInfo wifi = connMgr
					.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

			final android.net.NetworkInfo mobile = connMgr
					.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

			wifiStatus = wifi.isAvailable();
			mobileStatus = mobile.isAvailable();
		} catch (Exception e) {
			e.printStackTrace();
		}

		// SD card
//		sdStatus = android.os.Environment.getExternalStorageState().equals(
//				android.os.Environment.MEDIA_MOUNTED);
		sdStatus = android.os.Environment.getExternalStorageState();

		listAdapter.clear();
		listAdapter.add("Client Name: " + clientName);
		listAdapter.add("Client ID: " + clientID);
		listAdapter.add("Parameter Version: " + parameterVersion);
		listAdapter
				.add("Network Positioning enabled: " + networkPositionStatus);
		listAdapter.add("GPS Positioning enabled: " + gpsStatus);
		listAdapter.add("WIFI available: " + wifiStatus);
		listAdapter.add("Mobile available: " + mobileStatus);
		listAdapter.add("SD Card Status: " + sdStatus);
		listAdapter.add("Charging Status: " + chargingStatus);
		listAdapter.add("Permissions: " + permissions);
		listAdapter.add("Version Code: " + versionCode);
		listAdapter.add("Version Name: " + versionName);
		listAdapter.notifyDataSetChanged();
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case WAVEFORM_ID:
			Log.d(TAG, "launching intent for waveform viewer");
			Intent waveIntent = new Intent(ClientInfo.this,
					WaveformDisplay.class);
			startActivity(waveIntent);
			finish();
			break;
		case SHAKE_MAP_ID:
			Log.d(TAG, "TODO: launch intent for map");
			Intent alertIntent = new Intent(ClientInfo.this, ShakeAlertActivity.class);
			startActivity(alertIntent);
			finish();
			break;
		case QUIT_ID:
			System.out.println("quit...");
			stopService(new Intent(ClientInfo.this, ShakeAlertService.class));
			finish();
			break;
		}

		return super.onMenuItemSelected(featureId, item);
	}

}
